package com.asen.test.view.BesselCurve

import android.animation.*
import android.content.Context
import android.graphics.PointF
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.View
import android.view.animation.*
import android.widget.ImageView
import android.widget.RelativeLayout
import com.asen.libcommon.util.ScreenUtil
import com.asen.test.R
import java.util.*

/**
 * @author : asenLiang
 * @date   : 2021/9/6
 * @e-mail : liangAisiSen@163.com
 * @desc   : 贝塞尔曲线-类似点赞效果
 */
class SpotPraiseView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {

    private var mInterpolators: Array<Interpolator?> = arrayOfNulls(4)
    private var dWidth = 0
    private var mWidth = 0
    private var dHeight = 0
    private var mHeight = 0
    private var lp: LayoutParams? = null
    private val random = Random()


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //得到本布局的宽高
        mWidth = measuredWidth
        mHeight = measuredHeight
    }


    init {
        // 初始化插补器
        mInterpolators[0] = LinearInterpolator() // 线性
        mInterpolators[1] = AccelerateInterpolator() // 加速
        mInterpolators[2] = DecelerateInterpolator() // 减速
        mInterpolators[3] = AccelerateDecelerateInterpolator() // 先加速后减速

        // 获取图片宽高
//    dWidth = drawables[0].getIntrinsicWidth();
//    dHeight = drawables[0].getIntrinsicHeight();
        //手动设置宽高
        dWidth = ScreenUtil.dp2px(context, 40f)
        dHeight = ScreenUtil.dp2px(context, 40f)
        lp = LayoutParams(dWidth, dHeight)
        //设置view控件的起始位置
//    lp.addRule(CENTER_HORIZONTAL, TRUE);// 这里的TRUE 要注意 不是true
        lp!!.addRule(ALIGN_PARENT_RIGHT, TRUE)
        lp!!.addRule(ALIGN_PARENT_BOTTOM, TRUE)
    }


    /**
     * 进场动画，三种同时播放
     * alpha透明度 （80%-0%）
     * scaleX 宽度 target（20%-100%）
     * scaleY 高度
     *
     * @param target
     * @return
     */
    private fun getEnterAnimator(target: View): AnimatorSet {
        val alpha =
            ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f)
        val scaleX =
            ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f)
        val scaleY =
            ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f)
        val enter = AnimatorSet()
        enter.setTarget(target)
        enter.interpolator = LinearInterpolator()
        enter.setDuration(500).playTogether(alpha, scaleX, scaleY)
        return enter
    }


    private fun getBezierValueAnimator(target: View): ValueAnimator {
        // 初始化贝塞尔估值器
        //随机产生两个点，以确定一条3阶贝塞尔曲线
        val evaluator = BezierEvaluator(getPointF(2), getPointF(1))
        // 起点在底部中心位置，终点在底部随机一个位置，改变new PointF()中值来改变起始位置
//    ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) /
//        2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0));
        // 起点在右下角位置，终点在左上角位置
        val animator = ValueAnimator.ofObject(
            evaluator,
            PointF((mWidth - dWidth).toFloat(), (mHeight - dHeight).toFloat()),
            PointF(0f, 0f)
        )
        animator.setTarget(target)
        animator.addUpdateListener { valueAnimator -> // 这里获取到贝塞尔曲线计算出来的的x y值 赋值给view 这样就能让爱心随着曲线走啦
            val pointF = valueAnimator.animatedValue as PointF
            target.x = pointF.x
            target.y = pointF.y
            // alpha动画，根据运动距离改变透明度
//        target.setAlpha(1 - valueAnimator.getAnimatedFraction());
            target.alpha = 1 - valueAnimator.animatedFraction + 0.3f
        }
        animator.duration = 3000
        return animator
    }


    private fun getPointF(i: Int): PointF {
        val pointF = PointF()
        //pointF.x,pointF.y都是随机，因此可以产生n多种轨迹
        pointF.x = random.nextInt(100).toFloat() //0~loveLayout.Width

        //为了美观,建议尽量保证P2在P1上面,那怎么做呢??
        //只需要将该布局的高度分为上下两部分,让p1只能在下面部分范围内变化(1/2height~height),让p2只能在上面部分范围内变化(0~1/2height),因为坐标系是倒着的;

        //0~loveLayout.Height/2
        if (i == 1) {
            pointF.y = random.nextInt(mHeight / 2) + mHeight / 2.toFloat() //P1点Y轴坐标变化
        } else if (i == 2) { //P2点Y轴坐标变化
            pointF.y = random.nextInt(mHeight / 2).toFloat()
        }
        return pointF
    }


    fun addHeart(arr:Array<Drawable?>) {
        val imageView = ImageView(context)
        // 随机选一个爱心
        imageView.setImageDrawable(arr[random.nextInt(arr.size-1)])
        imageView.layoutParams = lp
        addView(imageView)
        val finalSet = AnimatorSet()
        val enterAnimatorSet = getEnterAnimator(imageView) //入场动画
        val bezierValueAnimator = getBezierValueAnimator(imageView) //贝塞尔曲线路径动画
        finalSet.playSequentially(enterAnimatorSet, bezierValueAnimator)
        //    finalSet.playSequentially(bezierValueAnimator);
        finalSet.interpolator = mInterpolators[random.nextInt(4)]
        finalSet.setTarget(imageView)
        finalSet.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)
                removeView(imageView) //删除爱心
            }
        })
        finalSet.start()
    }

    class BezierEvaluator(private val mControlP1: PointF, private val mControlP2: PointF) :
        TypeEvaluator<PointF> {
        override fun evaluate(time: Float, start: PointF, end: PointF): PointF {
            val timeLeft = 1.0f - time
            val point = PointF()
            point.x =
                timeLeft * timeLeft * timeLeft * start.x + 3 * timeLeft * timeLeft * time * mControlP1.x + 3 * timeLeft * time * time * mControlP2.x + time * time * time * end.x
            point.y =
                timeLeft * timeLeft * timeLeft * start.y + 3 * timeLeft * timeLeft * time * mControlP1.y + 3 * timeLeft * time * time * mControlP2.y + time * time * time * end.y
            return point
        }
    }


}

